# plot two images
def plot_2_images(_im1, _im2, _text1, _text2):
plt.figure(figsize=(17,9))
plt.subplot(1,2,1)
if (len(_im1.shape)==3):
plt.imshow(_im1)
else:
plt.imshow(_im1,cmap='gray')
plt.title(_text1)
plt.subplot(1,2,2)
if (len(_im2.shape)==3):
plt.imshow(_im2)
else:
plt.imshow(_im2,cmap='gray')
plt.title(_text2)
# plot 3 images
def plot_3_images(_im1, _im2, _im3, _text1='', _text2='', _text3=''):
plt.figure(figsize=(17,9))
plt.subplot(1,3,1)
if (len(_im1.shape)==3):
plt.imshow(_im1)
else:
plt.imshow(_im1,cmap='gray')
plt.title(_text1)
plt.subplot(1,3,2)
if (len(_im2.shape)==3):
plt.imshow(_im2)
else:
plt.imshow(_im2,cmap='gray')
plt.title(_text2)
plt.subplot(1,3,3)
if (len(_im3.shape)==3):
plt.imshow(_im3)
else:
plt.imshow(_im3,cmap='gray')
plt.title(_text3)
# plots images
def plot_images(_ims,_names):
_n_images = len(_ims)
_figsize = (17, _n_images*2)
# initialize
plt.figure(figsize = _figsize)
_plot_shape = (_n_images//2, 2) # to display calibration images
for k in range(_n_images):
plt.subplot(_plot_shape[0],_plot_shape[1],k+1)
if (len(_ims.shape) == 4):
plt.imshow(_ims[k])
else:
plt.imshow(_ims[k],cmap='gray')
plt.title(_names[k])
# reads images and converts to gray
def get_images(_path):
_fnames = glob.glob(_path)
_n_images = len(_fnames)
print("Found {} images: ".format(_n_images),end = '')
names = list()
for i in range(_n_images):
_out = _fnames[i].split('/')
names.append(_out[-1])
print(names[i],', ', end='')
_shape = (mpimg.imread(_fnames[0])).shape # read an image
im_rgb = np.zeros((_n_images,_shape[0],_shape[1],_shape[2])).astype(np.uint8)
im_gry = np.zeros((_n_images,_shape[0],_shape[1])).astype(np.uint8)
for k, fname in enumerate(_fnames):
im_rgb[k] = mpimg.imread(fname)
im_gry[k] = cv2.cvtColor(im_rgb[k],cv2.COLOR_RGB2GRAY)
return(im_rgb, im_gry, names)
# convert csapce from RGB
def convert_color(_image, cspace):
if (cspace != 'RGB'):
if cspace == 'HSV':
_conv_image = cv2.cvtColor(_image, cv2.COLOR_RGB2HSV)
elif cspace == 'GRY':
_conv_image = cv2.cvtColor(_image, cv2.COLOR_RGB2GRAY)
elif cspace == 'LUV':
_conv_image = cv2.cvtColor(_image, cv2.COLOR_RGB2LUV)
elif cspace == 'HLS':
_conv_image = cv2.cvtColor(_image, cv2.COLOR_RGB2HLS)
elif cspace == 'YUV':
_conv_image = cv2.cvtColor(_image, cv2.COLOR_RGB2YUV)
elif cspace == 'YCrCb':
_conv_image = cv2.cvtColor(_image, cv2.COLOR_RGB2YCrCb)
else:
_conv_image = np.copy(_image)
return(_conv_image)
# for classifier training: read all images/labels from a single path, x=images, y=labels
def get_x_y(_path,_is_object,cspace,channel):
# _path = directory path
# _is_object = _path label
# cspace = color space
# channel = 0,1,2, or negative (all)
_fnames = glob.glob(_path)
# get image parameters
n_images = len(_fnames)
_shape = (mpimg.imread(_fnames[0])).shape
print(' {:30}, with {} images'.format(_path,n_images))
if (channel < 0):
X = np.zeros((n_images,_shape[0],_shape[1],_shape[2])).astype(np.float64)
else:
X = np.zeros((n_images,_shape[0],_shape[1])).astype(np.float64)
Y = np.zeros(n_images).astype(np.bool_)
for i in range(n_images):
_image = mpimg.imread(_fnames[i])
_feature_image = convert_color(_image, cspace)
if ((cspace == 'GRY') or (channel<0)):
X[i] = _feature_image[:,:]
else:
X[i] = _feature_image[:,:,channel]
Y[i] = _is_object
return(X,Y)
# for classifier training: read images from multiple paths
def get_X_Y(_paths,_are_objects,cspace,channel):
print('directories included:')
cars = 0
not_cars = 0
for i in range(len(_paths)):
_X,_Y = get_x_y(_paths[i],_are_objects[i],cspace,channel)
if (_are_objects[i] == True):
cars = cars + len(_Y)
else:
not_cars = not_cars + len(_Y)
if (i==0):
X = _X
Y = _Y
else:
X = np.concatenate((X,_X))
Y = np.concatenate((Y,_Y))
print('shape of X = {}'.format(X.shape))
print('ratio of cars to total images = {}/{}={:.2}'.format(cars,cars+not_cars,cars/(cars+not_cars)))
return(X,Y)
# color histogram: from lecture notes
def get_color_hist(img, nbins): #bins_range=(0, 256)
# Compute the histogram of the color channels separately
channel1_hist = np.histogram(img[:,:,0], bins=nbins)
channel2_hist = np.histogram(img[:,:,1], bins=nbins)
channel3_hist = np.histogram(img[:,:,2], bins=nbins)
# Concatenate the histograms into a single feature vector
hist_features = np.concatenate((channel1_hist[0], channel2_hist[0], channel3_hist[0]))
# Return the individual histograms, bin_centers and feature vector
return(hist_features)
# window --> feature
def get_hog_feature(_im_1ch, _hog_bins, _ppc, _cpb, _with_vis, _with_fv):
if (_with_vis):
_feature, _vis = (hog(_im_1ch, orientations=_hog_bins, pixels_per_cell=(_ppc,_ppc),
cells_per_block=(_cpb,_cpb),
visualise=_with_vis, feature_vector=_with_fv))
return(_feature, _vis)
else:
_feature = (hog(_im_1ch, orientations=_hog_bins, pixels_per_cell=(_ppc,_ppc),
cells_per_block=(_cpb,_cpb),
visualise=_with_vis, feature_vector=_with_fv))
return(_feature)
# window --> hog: extraxts hog feature from image
def get_hog_features(_im, _hog_bins,_ppc, _cpb, _with_vis, _with_fv):
assert(_with_vis == False)
if (len(_im.shape) == 2):
return(get_feature(_im,_with_vis, _with_fv))
else:
feature0 = get_hog_feature(_im[:,:,0], _hog_bins, _ppc,_cpb, _with_vis, _with_fv)
feature1 = get_hog_feature(_im[:,:,1], _hog_bins,_ppc,_cpb, _with_vis, _with_fv)
feature2 = get_hog_feature(_im[:,:,2],_hog_bins,_ppc,_cpb, _with_vis, _with_fv)
return(np.hstack((feature0, feature1, feature2)))
# all images --> features (for training classifier)
def get_F(_X,_hog_bins,_ppc, _cpb, _hist_bins):
# allocate memory
width_hog = len(get_hog_features(_X[0], _hog_bins, _ppc, _cpb, False, True))
width_his = len(get_color_hist(_X[0], _hist_bins))
width = width_hog + width_his
height = len(X)
F = np.zeros((height,width)).astype(np.float64)
for i in range(height):
hog_features = get_hog_features(_X[i], _hog_bins, _ppc, _cpb, False, True)
his_features = get_color_hist(_X[i], _hist_bins)
F[i] = np.hstack((his_features, hog_features))
return(F)
# This function drwas boxes around an image (from lecture notes)
def draw_boxes(img, bboxes, color=(0, 0, 255), thick=6):
imcopy = np.copy(img)
for bbox in bboxes:
cv2.rectangle(imcopy, bbox[0], bbox[1], color, thick)
return(imcopy)
# explore boxes, returns all boxes considered
def explore_boxes(img, y_lim, x_lim, scale, intervalx,orient, pix_per_cell, cell_per_block,cspace):
boxes = []
window = pix_per_cell * cell_per_block
assert(window == 64)
for j in range(len(scale)):
# (a) pick portion of image that is of interest and convert to CSAPCE used
im_of_interest = convert_color(img[y_lim[j][0]:y_lim[j][1],x_lim[j][0]:x_lim[j][1],:], cspace)
# (b) scale image
if (scale[j] != 1):
imshape = im_of_interest.shape
im_of_interest = cv2.resize(im_of_interest, (np.int(imshape[1]/scale[j]), np.int(imshape[0]/scale[j])))
# (c) do hog on image
ch1 = im_of_interest[:,:,0]
hog1 = get_hog_feature(ch1, orient, pix_per_cell, cell_per_block, False, False)
assert(hog1.shape[0] > 0)
assert(hog1.shape[1] > 0)
print('scaled image shape =',ch1.shape)
print('hog shape =',hog1.shape)
plt.figure(figsize=(17,14))
plt.imshow(ch1,cmap='gray')
for xpos in range(0,hog1.shape[1],intervalx[j]):
for ypos in range(hog1.shape[0]):
# back to unscaled pixel domain
_left = np.int(xpos*pix_per_cell*scale[j])
_top = np.int(ypos*pix_per_cell*scale[j])
_width = np.int(window*scale[j])
upper_left = (_left+x_lim[j][0], _top+y_lim[j][0])
lower_right = (upper_left[0]+_width, upper_left[1]+_width)
boxes.append((upper_left, lower_right))
return(boxes)
# returns all boxes that were detected positive
def find_boxes(img, y_lim, x_lim, scale, intervalx, svc, X_scaler, orient, pix_per_cell,
cell_per_block,hist_bins,cspace):
boxes = []
window = pix_per_cell * cell_per_block
assert(window == 64)
img = img.astype(np.float32)/255
for j in range(len(scale)):
# (a) pick portion of image that is of interest and convert to appropriate CSAPCE
im_of_interest = convert_color(img[y_lim[j][0]:y_lim[j][1],x_lim[j][0]:x_lim[j][1],:], cspace)
# (b) scale image
if (scale[j] != 1):
imshape = im_of_interest.shape
im_of_interest = cv2.resize(im_of_interest, (np.int(imshape[1]/scale[j]), np.int(imshape[0]/scale[j])))
# (c) do hog on portion of image of interest
hog1 = get_hog_feature(im_of_interest[:,:,0], orient, pix_per_cell, cell_per_block, False, False)
hog2 = get_hog_feature(im_of_interest[:,:,1], orient, pix_per_cell, cell_per_block, False, False)
hog3 = get_hog_feature(im_of_interest[:,:,2], orient, pix_per_cell, cell_per_block, False, False)
assert(hog1.shape[0] > 0)
assert(hog1.shape[1] > 0)
# (d) for each window: generate features, classify and box
for x_cell in range(0,hog1.shape[1],intervalx[j]):
for y_cell in range(hog1.shape[0]):
# 1. hog feature
hog_feat1 = hog1[y_cell, x_cell].ravel()
hog_feat2 = hog2[y_cell, x_cell].ravel()
hog_feat3 = hog3[y_cell, x_cell].ravel()
hog_features = np.hstack((hog_feat1, hog_feat2, hog_feat3))
# 2. color histogram feature
ytop = y_cell * pix_per_cell
xleft = x_cell * pix_per_cell
subimg = im_of_interest[ytop:ytop+window, xleft:xleft+window]
hist_features = get_color_hist(subimg, nbins=hist_bins)
# 3. classifier
test_features = X_scaler.transform(np.hstack((hist_features, hog_features)).reshape(1, -1))
test_prediction = svc.predict(test_features)
# 4. box
if (test_prediction == 1):
_left = np.int(xleft*scale[j])
_top = np.int(ytop*scale[j])
_width = np.int(window*scale[j])
upper_left = (_left+x_lim[j][0], _top+y_lim[j][0])
lower_right = (upper_left[0]+_width, upper_left[1]+_width)
boxes.append((upper_left, lower_right))
return(boxes)
# from lecture notes
def add_heat(heatmap, bbox_list):
for box in bbox_list:
# each "box" is of form ((x1, y1), (x2, y2))
heatmap[box[0][1]:box[1][1], box[0][0]:box[1][0]] += 1
return(heatmap)
# from lecture notes
def apply_threshold(heatmap, threshold):
thr = np.copy(heatmap)
thr[thr <= threshold] = 0
# Return thresholded map
return(thr)
# from lecture notes
def draw_labeled_bboxes(img, labels):
_im_b = np.copy(img)
# Iterate through all detected cars
for car_number in range(1, labels[1]+1):
# Find pixels with each car_number label value
nonzero = (labels[0] == car_number).nonzero()
# Identify x and y values of those pixels
nonzeroy = np.array(nonzero[0])
nonzerox = np.array(nonzero[1])
# Define a bounding box based on min/max x and y
bbox = ((np.min(nonzerox), np.min(nonzeroy)), (np.max(nonzerox), np.max(nonzeroy)))
# Draw the box on the image
cv2.rectangle(_im_b, bbox[0], bbox[1], (0,0,255), 6)
# Return the image
return(_im_b)